package com.zhdl.hardware.motor.leisai.repository.impl;

import cn.hutool.core.util.HexUtil;
import com.google.common.eventbus.Subscribe;
import com.project.command.faq.event.behavior.BehaviorPerform;
import com.project.command.instruction.strategy.process.data.AfterStrategyParam;
import com.project.common.util.DelayUtil;
import com.zhdl.common.ytools.BaseConversionTools;
import com.zhdl.common.ytools.callback.CommonCallback;
import com.zhdl.common.ytools.eventbus.center.EventBusCenter;
import com.zhdl.hardware.motor.leisai.repository.LeisaiMotorCmdHandleDao;
import com.zhdl.network.other_protocol.modbusrtu.ModbusRtuRespPkg;
import com.zhdl.network.other_protocol.modbusrtu.dto.ModbusDto;
import com.zhdl.network.other_protocol.modbusrtu.request.WriteSingleKeepRegisterReq;
import com.zhdl.network.strategy.common.ProtocolContext;
import com.zhdl.network.strategy.modbusrtu.ModbusRtuStrategy;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 雷赛电机-指令处理层
 */
@Slf4j
public class LeisaiMotorCmdHandleDaoImpl implements LeisaiMotorCmdHandleDao {

    /**
     * 汇川电机-串口
     */
    public String port;
    /**
     * 通信协议处理
     */
    public ProtocolContext protocolContext;
    /**
     * Callback 回调管理
     */
    public Map<String, CommonCallback<String>> commonCallbackMap = new ConcurrentHashMap<>();

    public LeisaiMotorCmdHandleDaoImpl(String port, BehaviorPerform behaviorPerform) {
        EventBusCenter.getEventBus().register(this);
        protocolContext = new ProtocolContext(new ModbusRtuStrategy(port, behaviorPerform));
        this.port = port;
    }

    @Subscribe
    public void dataReception(AfterStrategyParam event) {
        /* 判断当前串口 */
        if (port.equals(event.getPortKey())) {
            /* 获取电机指令返回的数据 */
            //此处接收串口或网口客户端回应代码,并处理
            List<ModbusDto> list = event.getNewData();
            ModbusDto modbusDto = list.get(0);

            String instruction = event.getInstruction();
            instruction = instruction.replaceAll(" ", "");
            instruction = instruction.toUpperCase();
            for (String cmd : commonCallbackMap.keySet()) {
                String temp = cmd.toUpperCase();
                if (temp.contains(instruction)) {
                    commonCallbackMap.get(cmd).statusCallback(HexUtil.encodeHexStr(modbusDto.getUnitBuff()));
                    commonCallbackMap.remove(cmd);
                }
            }
        }
    }

    /**
     * 雷赛电机-电机移动速度
     *
     * @param slaveStationId 从站Id
     * @param address        寄存器地址
     * @param value          写入值
     */
    @Override
    public void leisaiSetMoveSpeed(String slaveStationId, String address, int value) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddress(address);
        req.setWriteValue(BaseConversionTools.intToIntHex(value));
        try {
            byte[] bytes = ModbusRtuRespPkg.WriteSingleKeepRegister(req);
            protocolContext.sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 雷赛电机-电机移动距离
     *
     * @param slaveStationId 从站Id
     * @param address        寄存器地址
     * @param moveDist       移动距离
     */
    @Override
    public void leisaiSetMoveDist(String slaveStationId, String address, int moveDist) {
        String distance = BaseConversionTools.intToIntHex(moveDist);
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddress(address);
        req.setWriteValue(distance);
        try {
            /* 电机设置运动距离 */
            byte[] bytes = ModbusRtuRespPkg.WriteMoreKeepRegister(req);
            protocolContext.sendCmd(HexUtil.encodeHexStr(bytes));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        /* 电机设置使能 */
        DelayUtil.delayedExecution(20, () -> {
            protocolContext.sendCmd("01066002001037C6");
            log.info("电机使能___");
        });
    }

    /**
     * 雷赛电机-读取电机位置
     *
     * @param slaveStationId 从站Id
     */
    @Override
    public void leisaiReadCurrentLocation(String slaveStationId, CommonCallback<String> callback) {
        WriteSingleKeepRegisterReq req = new WriteSingleKeepRegisterReq();
        req.setId(slaveStationId);
        req.setStartAddress("602C");
        req.setWriteValue("0002");
        try {
            byte[] bytes = ModbusRtuRespPkg.ReadSingleKeepRegister(req);
            protocolContext.sendCmd(HexUtil.encodeHexStr(bytes));
            commonCallbackMap.put(
                    HexUtil.encodeHexStr(bytes) + "_" +
                            System.currentTimeMillis(), callback);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
